const Get = require('../template')

console.log("=== Get 复杂场景测试 ===")

// 测试多层循环引用获取
console.log(
  "多层循环引用获取:", (() => {
    const obj1 = { id: 1, name: 'obj1' }
    const obj2 = { id: 2, name: 'obj2' }
    const obj3 = { id: 3, name: 'obj3' }

    obj1.ref = obj2
    obj2.ref = obj3
    obj3.ref = obj1

    return Get.get(obj1, 'id') === 1 &&
      Get.get(obj1, 'name') === 'obj1' &&
      Get.get(obj1, 'ref.id') === 2 &&
      Get.get(obj1, 'ref.name') === 'obj2' &&
      Get.get(obj1, 'ref.ref.id') === 3 &&
      Get.get(obj1, 'ref.ref.name') === 'obj3' &&
      Get.get(obj1, 'ref.ref.ref.id') === 1 &&
      Get.get(obj1, 'ref.ref.ref.name') === 'obj1'
  })()
)

// 测试混合类型复杂结构获取
console.log(
  "混合类型复杂结构获取:", (() => {
    const obj = {
      string: 'test',
      number: 42,
      boolean: true,
      null: null,
      undefined: undefined,
      array: [1, 'two', { three: 3 }],
      object: { nested: { deep: 'value' } },
      date: new Date('2023-01-01'),
      regex: /test/gi,
      function: function test() { return 'hello' },
      symbol: Symbol('test'),
      bigint: BigInt(123),
      map: new Map([['a', 1], ['b', 2]]),
      set: new Set([1, 2, 3]),
      typedArray: new Uint8Array([1, 2, 3]),
      arrayBuffer: new ArrayBuffer(8),
      dataView: new DataView(new ArrayBuffer(8)),
      error: new Error('test error')
    }

    return Get.get(obj, 'string') === 'test' &&
      Get.get(obj, 'number') === 42 &&
      Get.get(obj, 'boolean') === true &&
      Get.get(obj, 'null') === null &&
      Get.get(obj, 'undefined') === undefined &&
      Get.get(obj, 'array.0') === 1 &&
      Get.get(obj, 'array.1') === 'two' &&
      Get.get(obj, 'array.2.three') === 3 &&
      Get.get(obj, 'object.nested.deep') === 'value' &&
      Get.get(obj, 'date') instanceof Date &&
      Get.get(obj, 'date').getTime() === obj.date.getTime() &&
      Get.get(obj, 'regex') instanceof RegExp &&
      Get.get(obj, 'regex').source === obj.regex.source &&
      Get.get(obj, 'regex').flags === obj.regex.flags &&
      Get.get(obj, 'function') === obj.function &&
      Get.get(obj, 'symbol') === obj.symbol &&
      Get.get(obj, 'bigint') === obj.bigint &&
      Get.get(obj, 'map') === obj.map &&
      Get.get(obj, 'set') === obj.set &&
      Get.get(obj, 'typedArray') === obj.typedArray &&
      Get.get(obj, 'arrayBuffer') === obj.arrayBuffer &&
      Get.get(obj, 'dataView') === obj.dataView &&
      Get.get(obj, 'error') === obj.error
  })()
)

// 测试深度嵌套数组获取
console.log(
  "深度嵌套数组获取:", (() => {
    let arr = [1, 2, 3]
    for (let i = 0; i < 10; i++) {
      arr = [arr, { level: i, data: `level${i}` }]
    }

    let current = arr
    for (let i = 0; i < 10; i++) {
      if (Get.get(current, '1.level') !== i) return false
      if (Get.get(current, '1.data') !== `level${i}`) return false
      current = Get.get(current, '0')
    }

    return Get.get(current, '0') === 1 &&
      Get.get(current, '1') === 2 &&
      Get.get(current, '2') === 3
  })()
)

// 测试原型链继承获取
console.log(
  "原型链继承获取:", (() => {
    function BaseClass() {
      this.baseProp = 'base'
    }
    BaseClass.prototype.baseMethod = function() { return 'base method' }

    function DerivedClass() {
      BaseClass.call(this)
      this.derivedProp = 'derived'
    }
    DerivedClass.prototype = Object.create(BaseClass.prototype)
    DerivedClass.prototype.constructor = DerivedClass
    DerivedClass.prototype.derivedMethod = function() { return 'derived method' }

    const instance = new DerivedClass()

    return Get.get(instance, 'baseProp') === 'base' &&
      Get.get(instance, 'derivedProp') === 'derived' &&
      Get.get(instance, 'baseMethod') === instance.baseMethod &&
      Get.get(instance, 'derivedMethod') === instance.derivedMethod
  })()
)

// 测试自定义类实例获取
console.log(
  "自定义类实例获取:", (() => {
    class CustomClass {
      constructor(value) {
        this.value = value
        this.timestamp = new Date()
      }

      getValue() {
        return this.value
      }

      setValue(newValue) {
        this.value = newValue
      }
    }

    const instance = new CustomClass('test')

    return Get.get(instance, 'value') === 'test' &&
      Get.get(instance, 'timestamp') instanceof Date &&
      Get.get(instance, 'timestamp').getTime() === instance.timestamp.getTime() &&
      Get.get(instance, 'getValue') === instance.getValue &&
      Get.get(instance, 'setValue') === instance.setValue
  })()
)

// 测试稀疏数组获取
console.log(
  "稀疏数组获取:", (() => {
    const arr = new Array(1000)
    arr[0] = 'first'
    arr[999] = 'last'
    arr[500] = 'middle'

    return Get.get(arr, '0') === 'first' &&
      Get.get(arr, '500') === 'middle' &&
      Get.get(arr, '999') === 'last' &&
      Get.get(arr, '1') === undefined &&
      Get.get(arr, '998') === undefined
  })()
)

// 测试TypedArray嵌套获取
console.log(
  "TypedArray嵌套获取:", (() => {
    const obj = {
      uint8Array: new Uint8Array([1, 2, 3]),
      int16Array: new Int16Array([100, 200, 300]),
      float32Array: new Float32Array([1.1, 2.2, 3.3]),
      nested: {
        uint32Array: new Uint32Array([1000, 2000, 3000]),
        int8Array: new Int8Array([-1, -2, -3])
      }
    }

    return Get.get(obj, 'uint8Array') === obj.uint8Array &&
      Get.get(obj, 'uint8Array.0') === 1 &&
      Get.get(obj, 'uint8Array.1') === 2 &&
      Get.get(obj, 'uint8Array.2') === 3 &&
      Get.get(obj, 'int16Array') === obj.int16Array &&
      Get.get(obj, 'int16Array.0') === 100 &&
      Get.get(obj, 'int16Array.1') === 200 &&
      Get.get(obj, 'int16Array.2') === 300 &&
      Get.get(obj, 'float32Array') === obj.float32Array &&
      Math.abs(Get.get(obj, 'float32Array.0') - 1.1) < 0.001 &&
      Math.abs(Get.get(obj, 'float32Array.1') - 2.2) < 0.001 &&
      Math.abs(Get.get(obj, 'float32Array.2') - 3.3) < 0.001 &&
      Get.get(obj, 'nested.uint32Array') === obj.nested.uint32Array &&
      Get.get(obj, 'nested.uint32Array.0') === 1000 &&
      Get.get(obj, 'nested.uint32Array.1') === 2000 &&
      Get.get(obj, 'nested.uint32Array.2') === 3000 &&
      Get.get(obj, 'nested.int8Array') === obj.nested.int8Array &&
      Get.get(obj, 'nested.int8Array.0') === -1 &&
      Get.get(obj, 'nested.int8Array.1') === -2 &&
      Get.get(obj, 'nested.int8Array.2') === -3
  })()
)

// 测试Map和Set嵌套获取
console.log(
  "Map和Set嵌套获取:", (() => {
    const map1 = new Map([['a', 1], ['b', 2]])
    const map2 = new Map([['c', 3], ['d', 4]])
    const set1 = new Set([1, 2, 3])
    const set2 = new Set([4, 5, 6])

    const obj = {
      maps: { map1, map2 },
      sets: { set1, set2 },
      nested: {
        map: new Map([['nested', 'value']]),
        set: new Set(['nested'])
      }
    }

    return Get.get(obj, 'maps.map1') === map1 &&
      Get.get(obj, 'maps.map2') === map2 &&
      Get.get(obj, 'sets.set1') === set1 &&
      Get.get(obj, 'sets.set2') === set2 &&
      Get.get(obj, 'nested.map') === obj.nested.map &&
      Get.get(obj, 'nested.set') === obj.nested.set
  })()
)

// 测试Error对象嵌套获取
console.log(
  "Error对象嵌套获取:", (() => {
    const error1 = new Error('First error')
    error1.code = 'ERR_001'
    error1.details = { line: 10, column: 5 }

    const error2 = new TypeError('Second error')
    error2.code = 'ERR_002'
    error2.stack = 'TypeError: Second error\n    at test.js:15:10'

    const obj = {
      errors: [error1, error2],
      nested: {
        error: new ReferenceError('Third error'),
        data: { message: 'test' }
      }
    }

    return Get.get(obj, 'errors.0') === error1 &&
      Get.get(obj, 'errors.0.message') === 'First error' &&
      Get.get(obj, 'errors.0.code') === 'ERR_001' &&
      Get.get(obj, 'errors.0.details.line') === 10 &&
      Get.get(obj, 'errors.0.details.column') === 5 &&
      Get.get(obj, 'errors.1') === error2 &&
      Get.get(obj, 'errors.1.message') === 'Second error' &&
      Get.get(obj, 'errors.1.code') === 'ERR_002' &&
      Get.get(obj, 'errors.1.stack') === 'TypeError: Second error\n    at test.js:15:10' &&
      Get.get(obj, 'nested.error') === obj.nested.error &&
      Get.get(obj, 'nested.error.message') === 'Third error' &&
      Get.get(obj, 'nested.data.message') === 'test'
  })()
)

// 测试Date对象嵌套获取
console.log(
  "Date对象嵌套获取:", (() => {
    const date1 = new Date('2023-01-01')
    const date2 = new Date('2023-12-31')
    const date3 = new Date('2023-06-15')

    const obj = {
      dates: [date1, date2, date3],
      nested: {
        created: date1,
        updated: date2,
        metadata: {
          timestamp: date3,
          data: 'test'
        }
      }
    }

    return Get.get(obj, 'dates.0') === date1 &&
      Get.get(obj, 'dates.0') instanceof Date &&
      Get.get(obj, 'dates.0').getTime() === date1.getTime() &&
      Get.get(obj, 'dates.1') === date2 &&
      Get.get(obj, 'dates.1') instanceof Date &&
      Get.get(obj, 'dates.1').getTime() === date2.getTime() &&
      Get.get(obj, 'dates.2') === date3 &&
      Get.get(obj, 'dates.2') instanceof Date &&
      Get.get(obj, 'dates.2').getTime() === date3.getTime() &&
      Get.get(obj, 'nested.created') === date1 &&
      Get.get(obj, 'nested.created') instanceof Date &&
      Get.get(obj, 'nested.created').getTime() === date1.getTime() &&
      Get.get(obj, 'nested.updated') === date2 &&
      Get.get(obj, 'nested.updated') instanceof Date &&
      Get.get(obj, 'nested.updated').getTime() === date2.getTime() &&
      Get.get(obj, 'nested.metadata.timestamp') === date3 &&
      Get.get(obj, 'nested.metadata.timestamp') instanceof Date &&
      Get.get(obj, 'nested.metadata.timestamp').getTime() === date3.getTime() &&
      Get.get(obj, 'nested.metadata.data') === 'test'
  })()
)

// 测试RegExp对象嵌套获取
console.log(
  "RegExp对象嵌套获取:", (() => {
    const regex1 = /test/gi
    const regex2 = /pattern/im
    const regex3 = /example/gu

    const obj = {
      patterns: [regex1, regex2, regex3],
      nested: {
        email: /^[^\s@]+@[^\s@]+\.[^\s@]+$/,
        phone: /^\+?[\d\s-()]+$/,
        config: {
          url: /^https?:\/\/.+/,
          data: 'test'
        }
      }
    }

    return Get.get(obj, 'patterns.0') === regex1 &&
      Get.get(obj, 'patterns.0') instanceof RegExp &&
      Get.get(obj, 'patterns.0').source === 'test' &&
      Get.get(obj, 'patterns.0').flags === 'gi' &&
      Get.get(obj, 'patterns.1') === regex2 &&
      Get.get(obj, 'patterns.1') instanceof RegExp &&
      Get.get(obj, 'patterns.1').source === 'pattern' &&
      Get.get(obj, 'patterns.1').flags === 'im' &&
      Get.get(obj, 'patterns.2') === regex3 &&
      Get.get(obj, 'patterns.2') instanceof RegExp &&
      Get.get(obj, 'patterns.2').source === 'example' &&
      Get.get(obj, 'patterns.2').flags === 'gu' &&
      Get.get(obj, 'nested.email') === obj.nested.email &&
      Get.get(obj, 'nested.email') instanceof RegExp &&
      Get.get(obj, 'nested.email').source === '^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$' &&
      Get.get(obj, 'nested.phone') === obj.nested.phone &&
      Get.get(obj, 'nested.phone') instanceof RegExp &&
      Get.get(obj, 'nested.phone').source === '^\\+?[\\d\\s-()]+$' &&
      Get.get(obj, 'nested.config.url') === obj.nested.config.url &&
      Get.get(obj, 'nested.config.url') instanceof RegExp &&
      Get.get(obj, 'nested.config.url').source === '^https?:\\/\\/.+' &&
      Get.get(obj, 'nested.config.data') === 'test'
  })()
)

// 测试Symbol对象嵌套获取
console.log(
  "Symbol对象嵌套获取:", (() => {
    const sym1 = Symbol('test1')
    const sym2 = Symbol('test2')
    const sym3 = Symbol('test3')

    const obj = {
      symbols: [sym1, sym2, sym3],
      nested: {
        key1: sym1,
        key2: sym2,
        config: {
          key3: sym3,
          data: 'test'
        }
      }
    }

    return Get.get(obj, 'symbols.0') === sym1 &&
      Get.get(obj, 'symbols.0') === obj.symbols[0] &&
      Get.get(obj, 'symbols.1') === sym2 &&
      Get.get(obj, 'symbols.1') === obj.symbols[1] &&
      Get.get(obj, 'symbols.2') === sym3 &&
      Get.get(obj, 'symbols.2') === obj.symbols[2] &&
      Get.get(obj, 'nested.key1') === sym1 &&
      Get.get(obj, 'nested.key1') === obj.nested.key1 &&
      Get.get(obj, 'nested.key2') === sym2 &&
      Get.get(obj, 'nested.key2') === obj.nested.key2 &&
      Get.get(obj, 'nested.config.key3') === sym3 &&
      Get.get(obj, 'nested.config.key3') === obj.nested.config.key3 &&
      Get.get(obj, 'nested.config.data') === 'test'
  })()
)

// 测试BigInt对象嵌套获取
console.log(
  "BigInt对象嵌套获取:", (() => {
    const big1 = BigInt(123)
    const big2 = BigInt(456)
    const big3 = BigInt(789)

    const obj = {
      bigints: [big1, big2, big3],
      nested: {
        value1: big1,
        value2: big2,
        config: {
          value3: big3,
          data: 'test'
        }
      }
    }

    return Get.get(obj, 'bigints.0') === big1 &&
      Get.get(obj, 'bigints.0') === obj.bigints[0] &&
      Get.get(obj, 'bigints.1') === big2 &&
      Get.get(obj, 'bigints.1') === obj.bigints[1] &&
      Get.get(obj, 'bigints.2') === big3 &&
      Get.get(obj, 'bigints.2') === obj.bigints[2] &&
      Get.get(obj, 'nested.value1') === big1 &&
      Get.get(obj, 'nested.value1') === obj.nested.value1 &&
      Get.get(obj, 'nested.value2') === big2 &&
      Get.get(obj, 'nested.value2') === obj.nested.value2 &&
      Get.get(obj, 'nested.config.value3') === big3 &&
      Get.get(obj, 'nested.config.value3') === obj.nested.config.value3 &&
      Get.get(obj, 'nested.config.data') === 'test'
  })()
)

console.log("=== Get 复杂场景测试完成 ===")
